package ruc.TDEngine.read;

import cn.hutool.core.codec.Base64;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import ruc.Consts.constant;
import ruc.utils.IOUtils;
import ruc.TDEngine.TDEngine_Common;
import ruc.utils.Pval;
import cn.hutool.*;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

public class TDEngine_SingleThreadRead {
    private String IP, port, dbName, tbName,userName,password;

    public TDEngine_SingleThreadRead(String IP, String port, String dbName, String tbName, String userName, String password) {
        this.IP = IP;
        this.port = port;
        this.dbName = dbName;
        this.tbName = tbName;
        this.userName = userName;
        this.password = password;
    }

    public String DataUtil(long timeStamp) {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        return sdf.format(new Date(Long.parseLong(String.valueOf(timeStamp))));
    }

    public Request getRequest(String query) {
        String Authorization = Base64.encode(String.format("%s:%s", userName, password).getBytes(StandardCharsets.UTF_8));
        String URL = String.format("http://%s:%s/rest/sql", IP, port);

        return new Request.Builder()
                .url(URL)
                .method("POST", RequestBody.create(MediaType.parse("text/plain"),query))
                .addHeader("Authorization", "Basic "+Authorization)
                .addHeader("Content-Type", "text/plain")
                .build();
    }

    // p50、p90、p99
    private void execute(String eSql, int type) {
        long tol = 0;
        HashMap<Integer, List<Long>> m = new HashMap<>();
        for(int i = 0; i < 10000; i++) {
            long st_time = System.nanoTime();
            Response response = TDEngine_Common.send(getRequest(eSql));
            assert response != null;
            response.close();
            long ed_time = System.nanoTime();
            long diff = ed_time - st_time / constant.Ns2Ms;
            int key = Pval.check(diff); // 分桶
            if (m.containsKey(key)) {
                m.get(key).add(diff);
            } else {
                List<Long> l = new ArrayList<>();
                l.add(diff);
                m.put(key, l);
            }
            tol += diff;
        }

        System.out.printf("[TSBench-D] [TDEngine_query%d] >>>>> avg Response time：%d ms, pc50：%d ms, pc90:%d ms, pc99: %d ms >>>>>> \n", type, tol / 10000, Pval.calPVal(m, 50), Pval.calPVal(m, 90), Pval.calPVal(m, 99));
        IOUtils.WriteData(constant.GetWriteFilePath("TDEngine", "SingleThreadRead"),
                new String[]{String.valueOf(type), String.valueOf(tol / 10000), String.valueOf(Pval.calPVal(m, 50)), String.valueOf(Pval.calPVal(m, 90)), String.valueOf(Pval.calPVal(m, 99))});
    }

    //select max(cpu_usage) from ruc.d1 where hostname = "1" and server = "1" and ts >= "2021-12-28 19:15:09" and ts <= "2021-12-29 19:15:09" interval(10m);
    public void query1(String server, String hostName, long st, long ed, String interval) throws IOException {
        String sqlFormat = "select max(cpu_usage) from %s.%s where hostname = \"%s\" and server = \"%s\" and ts >= \"%s\" and ts <= \"%s\" interval(%s);";
        String eSql = String.format(sqlFormat, dbName, tbName, hostName, server, DataUtil(st), DataUtil(ed), interval);
        execute(eSql, 1);
    }

    //select max(cpu_usage), avg(memory_usage), sum(disk_usage) from ruc.d1 where(hostname = "1" or hostname = "2" or hostname = "3" or hostname = "4") and ts >= "2021-12-28 19:15:09" and ts <= "2021-12-28 19:16:49" interval(10m);
    public void query2(String h1, String h2, String h3, String h4,long st, long ed, String interval) throws IOException {
        String sqlFormat = "select max(cpu_usage), avg(memory_usage), sum(disk_usage) from %s.%s where(server = \"%s\" or server = \"%s\" or server = \"%s\" or server = \"%s\") and ts >= \"%s\" and ts <= \"%s\" interval(%s);";
        String eSql = String.format(sqlFormat, dbName, tbName, h1, h2, h3, h4, DataUtil(st), DataUtil(ed), interval);
        execute(eSql, 2);
    }

    //select max(disk_usage) from ruc.d1 where ts >= "2021-12-28 19:15:09" and ts <= "2021-12-28 19:16:49" interval(10m) order by ts desc;
    public void query3(long st, long ed, String interval) throws IOException {
        String sqlFormat = "select max(disk_usage) from %s.%s where ts >= \"%s\" and ts <= \"%s\" interval(%s) order by ts desc;";
        String eSql = String.format(sqlFormat, dbName, tbName, DataUtil(st), DataUtil(ed), interval);
        execute(eSql, 3);
    }


    public static void main(String[] args) throws IOException {
        TDEngine_SingleThreadRead db = new TDEngine_SingleThreadRead(constant.IP, constant.TDEngine_port, constant.dbName, constant.Concurrent_tbName, constant.userName, constant.passWord);
        String []serverList = constant.server;
        Random ran = new Random();

        db.query1(serverList[ran.nextInt(serverList.length)], "dde8784e-6f96-11ec-bd43-cd6282b60352", 1629877620000L, 1630643400000L, "10m");
        db.query2(serverList[ran.nextInt(serverList.length)], serverList[ran.nextInt(serverList.length)], serverList[ran.nextInt(serverList.length)], serverList[ran.nextInt(serverList.length)], 1629877620000L, 1630643400000L, "10m");
        db.query3(1629877620000L, 1630643400000L, "10m");
    }
}
